﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Modules.Constructor.Repositories;
using Modules.Project;
using Modules.System.Security;
using Modules.System.User;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Entity;
using PmSoft.Exceptions;

namespace Modules.Constructor
{
    /// <summary>
    /// 建设单位业务逻辑类
    /// </summary>
    [UseDI(ServiceLifetime.Scoped)]
    public class ConstructorService
    {
        private readonly ConstructorRepository constructorRepository;
        private readonly IApplicationContext applicationContext;
        private readonly SecurityRepository securityRepository;
        private readonly ConstructorCodeIndexer constructorCodeIndexer;
        private readonly ILogger logger;

        public ConstructorService(ConstructorRepository constructorRepository,
            SecurityRepository securityRepository,
            IApplicationContext applicationContext,
            ConstructorCodeIndexer constructorCodeIndexer,
            ILogger<ConstructorService> logger)
        {
            this.constructorRepository = constructorRepository;
            this.securityRepository = securityRepository;
            this.applicationContext = applicationContext;
            this.constructorCodeIndexer = constructorCodeIndexer;
            this.logger = logger;
        }

        /// <summary>
        /// 创建建设单位
        /// </summary>
        /// <param name="constructor"></param>
        /// <param name="password"></param>
        /// <exception cref="BusinessException"></exception>
        public void CreateConstructor(ConstructorInfo constructor, string password)
        {
            if (CodeExists(constructor.Code))
                throw new BusinessException($"建设单位:{constructor.Code}已存在");

            try
            {
                applicationContext.Transaction.Begin();//开始事务
                SysSecurity security = new();
                security.Password = SecurityPasswordHelper.EncodePassword(password, UserPasswordFormat.SM4);
                security.UserType = UserType.Constructor;
                securityRepository.Insert(security);
                constructor.SecurityId = security.SecurityId;//将安全信息表自增主键赋值给用户表
                constructorRepository.Insert(constructor);
                applicationContext.Transaction.Complete();//完成事务
            }
            catch (Exception ex)
            {
                applicationContext.Transaction.Abort();//回滚事务
                logger.LogError(ex, $"CreateConstructor Exception Code:{constructor.Code}");
                throw new BusinessException("写入建设单位信息数据失败");
            }
        }

        /// <summary>
        /// 无事务创建建设单位
        /// </summary>
        /// <param name="constructor"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        /// <exception cref="BusinessException"></exception>
        public ConstructorInfo CreateConstructorNoTransaction(ConstructorInfo constructor)
        {
            if (CodeExists(constructor.Code))
                throw new BusinessException($"建设单位:{constructor.Code}已存在");
            SysSecurity security = new();
            security.Password = SecurityPasswordHelper.EncodePassword(SecurityPasswordHelper.EncodePassword("Xzhr.123456", UserPasswordFormat.SM3), UserPasswordFormat.SM4);
            security.UserType = UserType.Constructor;
            securityRepository.Insert(security);
            constructor.SecurityId = security.SecurityId;//将安全信息表自增主键赋值给用户表
            constructorRepository.Insert(constructor);
            return constructor;
        }

        public bool CodeExists(string code)
        {
            return constructorRepository.CodeExists(code);
        }

        public ConstructorInfo? GetConstructorInfo(int constructorId)
        {
            return constructorRepository.Get(constructorId);
        }

        /// <summary>
        /// 通过建设单位名称获取建设单位信息
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public ConstructorInfo? GetConstructorInfoByName(string name)
        {
            return constructorRepository.GetConstructorInfoByName(name);
        }

        /// <summary>
        /// 根据名称获取所有建设单位信息
        /// </summary>
        /// <param name="names"></param>
        /// <returns></returns>
        public IEnumerable<ConstructorInfo> GetConstructorInfosByName(IEnumerable<string> names)
        {
            return constructorRepository.GetConstructorInfosByName(names);
        }

        /// <summary>
        /// 根据建设单位信用代码获取建设单位信息
        /// </summary>
        /// <param name="constructorCode"></param>
        /// <returns></returns>
        public ConstructorInfo? GetConstructorInfo(string constructorCode)
        {
            int? constructorId = constructorCodeIndexer.GetId(constructorCode);
            if (constructorId.HasValue && constructorId > 0)
                return GetConstructorInfo(constructorId.Value);
            return null;
        }

        public IPagedList<ConstructorInfo> GetConstructors(ConstructorQuery query, int pageIndex, int pageSize)
        {
            return constructorRepository.GetConstructors(query, pageIndex, pageSize);
        }

        /// <summary>
        /// 用户密码认证登录
        /// </summary>
        /// <param name="corpCode"></param>
        /// <param name="password"></param>
        public ConstructorInfo? PasswordSignIn(string corpCode, string password)
        {
            var security = GetSecurity(corpCode);
            if (security == null)
                throw new BusinessException("建设单位信用代码或密码错误");

            if (!SecurityPasswordHelper.CheckPassword(password, security.Password, UserPasswordFormat.SM4))
                throw new BusinessException("建设单位信用代码或密码错误");

            HandleLogin(security);

            return GetConstructorInfo(corpCode);
        }

        public SysSecurity? GetSecurity(string constructorCode)
        {
            var constructorInfo = GetConstructorInfo(constructorCode);
            if (constructorInfo == null)
                return null;
            return securityRepository.Get(constructorInfo.SecurityId);
        }

        /// <summary>
        /// 登陆处理
        /// </summary>
        /// <param name="security"></param>
        private void HandleLogin(SysSecurity security)
        {
            securityRepository.UpdateLoginInfoStatus(security, applicationContext.ClientIp, DateTime.Now);
        }

        public void UpdateDefaultProjectId(ConstructorInfo constructorInfo, int projectId)
        {
            constructorRepository.UpdateDefaultProjectId(constructorInfo, projectId);
        }

        public void Update(ConstructorInfo constructorInfo)
        {
            constructorRepository.Update(constructorInfo);
        }

        public object Insert(ConstructorInfo constructorInfo)
        {
            return constructorRepository.Insert(constructorInfo);
        }

        public void Delete(int id)
        {
           //var projects = applicationContext.GetService<project>().GetProjectCorpsByCorpId(id);
           // if(projects.Any())

            constructorCodeIndexer.Remove(id);//删除索引
            constructorRepository.DeleteByEntityId(id);
        }

        public void Deletes(IEnumerable<int> ids)
        {
            foreach (var id in ids)
            {
                Delete(id);
            }
        }
    }
}